package fudan.se.project.service.infrastructure.func.conference.resoure.paperalloc;


import fudan.se.project.domain.conference.Conference;
import fudan.se.project.domain.conference.Conference.AllocationStrategy;
import fudan.se.project.repository.entity.conference.ConferenceRepository;
import fudan.se.project.repository.entity.conference.production.ReviewInfoRepository;
import fudan.se.project.repository.entity.conference.role.PcMemberRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import static fudan.se.project.domain.conference.Conference.ConferenceStage.*;

@Service
public class PaperAllocateService {


    private final ConferenceRepository conferenceRepository;

    private static final int ASSIGNED_COUNT = 3;

    private final PaperAllocatorBalanced allocatorBalanced = new PaperAllocatorBalanced(ASSIGNED_COUNT);
    private final PaperAllocatorByTopic allocatorByTopic = new PaperAllocatorByTopic(ASSIGNED_COUNT);

    @Autowired
    public PaperAllocateService(ReviewInfoRepository reviewInfoRepository,
                                PcMemberRepository pcMemberRepository,
                                ConferenceRepository conferenceRepository) {
        this.conferenceRepository = conferenceRepository;

        allocatorBalanced.initialize(reviewInfoRepository);
        allocatorByTopic.initialize(pcMemberRepository,
                reviewInfoRepository);
    }


    public boolean process(Conference conference) {
        Conference.ConferenceStage stage = conference.getStage();

        if ((stage != CONTRIBUTION_START) && (stage != CONTRIBUTION_END)) {
            return false;
        }

        if (conference.getPcMembers().size() < ASSIGNED_COUNT) {
            return false;
        }

        if (conference.getPapers().isEmpty()) {
            return false;
        }

        boolean allocationResult;

        AllocationStrategy strategy = conference.getStrategy();
        AbstractPaperAllocator allocator = null;
        if (strategy.equals(AllocationStrategy.BALANCED)) {
            allocator = this.allocatorBalanced;
        } else if (strategy.equals(AllocationStrategy.BY_TOPIC)) {
            allocator = this.allocatorByTopic;
        }
        if (allocator == null) return false;
        allocationResult = allocator.allocatePapers(conference);

        if (allocationResult) {
            conference.setStage(REVIEW_START);
            conferenceRepository.save(conference);
        }
        return allocationResult;

    }


}
